{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 实例11：用Python给Excel所有工作表添加图片"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们在实例9里面展示了如何批量填写每日出货清单，每一天的清单都是直接复制“出货单模板”，然后在其中填入出货产品信息的。`openpyxl`有一个问题，就是在复制工作表的时候，无法跟着复制图片。而我们的公司名一般比较个性化，在Excel中用文字很难达到那个效果，比如如下：\n",
    "![](images\\company.png)\n",
    "\n",
    "此时，我们就需要使用到`openpyxl`模块的图片插入功能。但这个功能有一个坑，我们下面来展开说明。\n",
    "\n",
    "按照`openpyxl`的官方文档，添加图片只需如下几步：\n",
    "```python\n",
    "from openpyxl.drawing.image import Image #导入图片添加模块\n",
    "from openpyxl import load_workbook #导入Excel工作表操作模块\n",
    "img = Image('images\\company.png') #需添加的图片所在路径\n",
    "wb=load_workbook('data\\出货单.xlsx') #打开工作簿\n",
    "ws=wb[sheet_name] #获取工作表\n",
    "ws.add_image(img,'A1') #添加图片到指定的单元格\n",
    "wb.save('data\\出货单_new.xlsx') #保存文件\n",
    "```\n",
    "下面我们就按照以上说明来操作，看看效果怎么样。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "d:\\python\\lib\\site-packages\\ipykernel_launcher.py:5: DeprecationWarning: Call to deprecated function get_sheet_names (Use wb.sheetnames).\n",
      "  \"\"\"\n",
      "d:\\python\\lib\\zipfile.py:1355: UserWarning: Duplicate name: 'xl/media/image65.png'\n",
      "  return self._open_to_write(zinfo, force_zip64=force_zip64)\n"
     ]
    }
   ],
   "source": [
    "from openpyxl.drawing.image import Image\n",
    "from openpyxl import load_workbook\n",
    "img = Image('images\\company.png') #需添加的图片所在路径\n",
    "wb = load_workbook(\"data\\出货单.xlsx\") #打开工作簿\n",
    "sheet_names=wb.get_sheet_names() #获得工作簿的所有工作表名\n",
    "for sheet_name in sheet_names: #遍历每个工作表，并在每个工作表的A1单元格插入图片\n",
    "    ws=wb[sheet_name]\n",
    "    ws.add_image(img, 'A1')#添加图片到指定的A1单元格，图片左上角将与A1单元格左上角对齐\n",
    "wb.save('data\\出货单—new.xlsx')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们通过遍历“出货单.xlsx”文件中的所有工作表，然后每个工作表都在A1单元格插入我们设定好的图片，最后保存。待程序执行完成，打开保存的文件“出货单—new.xlsx”，报出如下错误：\n",
    "![](images\\error1.png)\n",
    "我们选择“是”，继续下一步，再报出错误：\n",
    "![](images\\error2.png)\n",
    "点击“关闭”，继续下一步。我们发现除了最后一个工作表“12-23”，其他工作表图片全部无法正常显示，都带有一个红色的“X”，显示为“无法显示该图片”。\n",
    "![](images\\last_page.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我花了很多时间来研究到底怎么回事，然后也做了很多测试。最后发现，每插入一张图片就需要保存一下，才可保证图片正常显示。因此将程序稍作修改如下。即每给一个工作表插入图片后，都保存一次，而不是给所有工作表插完图片后，最后才来保存。相当于我们不停地打开“出货单.xlsx”，然后在其中的各个工作表依次插入图片，每操作一次，保存一次。时间会比只保存一次更长，但毕竟比手动插入图片快很多了。最终，每张工作表都插入图片成功，呲牙..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "d:\\python\\lib\\site-packages\\ipykernel_launcher.py:4: DeprecationWarning: Call to deprecated function get_sheet_names (Use wb.sheetnames).\n",
      "  after removing the cwd from sys.path.\n"
     ]
    }
   ],
   "source": [
    "from openpyxl.drawing.image import Image\n",
    "img = Image('images\\company.png')\n",
    "wb = load_workbook(\"data\\出货单.xlsx\")\n",
    "sheet_names=wb.get_sheet_names()\n",
    "for sheet_name in sheet_names:\n",
    "    wb = load_workbook(\"data\\出货单.xlsx\")\n",
    "    ws=wb[sheet_name]\n",
    "    ws.add_image(img, 'A1')\n",
    "    wb.save('data\\出货单.xlsx')\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
